package com.anonymous.util.test;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import com.anonymous.message.ChatMsg;
import com.anonymous.message.Message;
import com.anonymous.util.NetworkUtils;

public class SSLServer{

	/**
	 * The port we will listen on
	 */
	private static int port = 6677;

	/**
	 * KeyStore for storing our public/private key pair
	 */
	private KeyStore clientKeyStore;

	/**
	 * KeyStore for storing the server's public key
	 */
	private KeyStore serverKeyStore;

	/**
	 * Used to generate a SocketFactory
	 */
	private SSLContext sslContext;


	/**
	 * Passphrase for accessing our authentication keystore
	 */
	static private final String passphrase = "serverpw";

	/**
	 * A source of secure random numbers
	 */
	static private SecureRandom secureRandom;

	/**
	 * Create a Server that listens on the given port. Start the background
	 * listening thread
	 */

	private X509Certificate clientCertificate; 
	private NetworkUtils networkUtils;
	
	public SSLServer() throws Exception{
		networkUtils = new NetworkUtils();
		run();
	}

	private void setupClientKeyStore() throws GeneralSecurityException,
			IOException {
		clientKeyStore = KeyStore.getInstance("JKS");
		//GENERATE AN EMPTY clientKeyStore
		clientKeyStore.load(null,
				passphrase.toCharArray());
        
	    // Add the certificate
	    clientKeyStore.setCertificateEntry("clientCertificate", clientCertificate);
	    clientKeyStore = null;
	}

	private void setupServerKeystore() throws GeneralSecurityException,
			IOException {
		serverKeyStore = KeyStore.getInstance("JKS");
		serverKeyStore.load(new FileInputStream("server.private"),
				passphrase.toCharArray());
	}

	private void setupSSLContext() throws GeneralSecurityException, IOException {
		TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
		tmf.init(clientKeyStore);

		KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
		kmf.init(serverKeyStore, passphrase.toCharArray());

		sslContext = SSLContext.getInstance("TLS");
		sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
				secureRandom);
	}


	public void run() {
		try {
			/*
			ServerSocket welcomeSocket = new ServerSocket(port);
			Socket serverNormalSocket = welcomeSocket.accept();
			System.out.println("1");
			Message msg = NetworkUtils.receive(serverNormalSocket);
			if(!msg.getFlag().equals("CERTIFICATE"))throw new Exception();
			clientCertificate = ((X509CertificateMsg)(msg)).getCertificate();
			NetworkUtils.send(new X509CertificateResultMsg(), serverNormalSocket);
			
			System.out.println("2");
			serverNormalSocket.close();
			*/
			Message msg;
			setupClientKeyStore();
			setupServerKeystore();
			setupSSLContext();

			SSLServerSocketFactory sf = sslContext.getServerSocketFactory();
			SSLServerSocket ss = (SSLServerSocket) sf.createServerSocket(port);

			// Require client authorization
			ss.setNeedClientAuth(false);

//			ss.setUseClientMode(true);

			System.out.println("Listening on port " + (port) + "...");
			Socket serverSocket = ss.accept();
			//	serverSocket.startHandshake();

			new SSLSend(serverSocket).start();
			while (true) {
				msg = networkUtils.receive(serverSocket);
				if(!msg.getFlag().equals("CHAT_MSG"))return;
				System.out.println(((ChatMsg)msg).getMessage());

				// ConnectionProcessor cp = new ConnectionProcessor(this,
				// socket);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}




	/**
	 * Create and start a Server. The port number must be provided on the
	 * command line
	 * @throws Exception 
	 */
	static public void main(String args[]) throws Exception {
		System.out
				.println("Wait while secure random numbers are initialized....");
		secureRandom = new SecureRandom();
		secureRandom.nextInt();
		System.out.println("Done.");

		new SSLServer();
	}
}
